package main

import (
	"fmt"

	"github.com/google/logger"
	"github.com/kataras/iris/v12"
	"github.com/topaz-h/iris-web/tools"
)

func main() {
	// 通过tools读取程序默认json配置信息
	config, err := tools.InitConfig("./config/config.json")
	if err != nil {
		logger.Error(err.Error())
	}

	// 调用newApp构建App
	app := newApp(config.StaticPath)

	// 应用App设置
	configation(app)

	// 路由设置
	mvcHandle(app)

	// 监听端口
	addr := ":" + config.Port
	app.Run(
		iris.Addr(addr), // 在端口9000进行监听
		iris.WithoutServerError(iris.ErrServerClosed), // 无服务错误提示
		iris.WithOptimizations,                        // 对json数据序列化更快的配置
	)
}

// 构建App
// @returns *iris.Application
func newApp(staticPath string) *iris.Application {
	//1.创建app结构体对象
	app := iris.New()

	//设置日志级别  开发阶段为debug
	app.Logger().SetLevel("debug")

	// 注册基本中间件
	// app.Use(recover.New())
	// app.Use(logger.New())
	// 前置中间件(每一个请求首先执行)：context.Handler 类型 app.Use(context.Handler)
	app.Use(func(ctx iris.Context) {
		ctx.Application().Logger().Infof("Begin request for path: %s", ctx.Path())
		ctx.Next()
	})
	// 全局中间件
	//在任何路由之前或之后，将中间件预先安排到所有路由
	// app.UseGlobal(handler1, handler2, handler3)
	// 后置中间件(每一个请求最后执行)：context.Handler 类型 app.Done(context.Handler) - 前一个执行了Next才会执行Done
	app.Done(func(ctx iris.Context) {
		ctx.Application().Logger().Info("Next()让我得以执行。Ending！！！")
	})

	// 跨域请求
	// corsOptions := cors.Options{
	// 	AllowedOrigins:   []string{"*", "http://foo.com"}, // 请求时Origin字段的值
	// 	AllowCredentials: true,                            // 是否允许发送Cookie(一般也只能设为true，因为若服务器不要浏览器发送Cookie，删除该字段即可)
	// 	//ExposedHeaders 该字段可选。CORS请求时，XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段该字段可选。
	// 	//6个基本字段：Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。
	// 	//如果想拿到其他字段，就必须在 ExposedHeaders 里面指定。
	// }
	// corsWrapper := cors.New(corsOptions).ServeHTTP
	// app.WrapRouter(corsWrapper)

	//注册静态资源
	fmt.Println(staticPath)
	/**
	* @description 函数会为你添加一个路由，它会将/yuorpath/yourfile.ico静态地提供给/yourfile.ico
	* @params favPath（string），声明 __.ico 的系统目录路径
	* @params  requestPath（string），路由的路径，默认是"/favicon.ico";因为有些浏览器首先会尝试默认获取.
	* 如果您有多个favicon（桌面，移动设备等），您可以显示声明自己的路径
	 */
	app.Favicon("./static/favicon.ico")
	// app.StaticServe("./static", staticPath)
	// app.StaticContent(staticPath, "./static", []byte{})
	// app.StaticEmbedded(staticPath, "./static")
	// app.StaticWeb(staticPath, "./static") //调用StaticHandler??? NOTICE: 文档上有此方法,实操失败

	//设置数据驱动的模板引擎为 std html/template(go 语言标准模板参见 html/template标准库)
	// Reload 方法设置为 true 表示开启开发者模式 将会每一次请求都重新加载 views 文件下的所有模板
	// RegisterView 注册加载 模板文件 与加载配置
	app.RegisterView(iris.HTML("./static", ".html").Reload(true))

	// homepage
	app.Get("/", func(ctx iris.Context) {
		// ctx.ViewData("Page", page)         // page为结构体
		ctx.View("index.html") // 可通过ViewData传递数据
		// ctx.ServeFile("index.html", false) // 按原样渲染视图(不显示???)
	})

	// 作为SPA的替代方案，您可以查看/routing /dynamic-path/root-wildcard
	// assetHandler := app.StaticHandler("./public", false, false)
	// app.SPA(assetHandler)
	return app
}

/**
 * 项目设置：字符编码+错误监听处理
 */
func configation(app *iris.Application) {
	//配置 字符编码
	app.Configure(iris.WithConfiguration(iris.Configuration{
		Charset: "UTF-8",
	}))

	//错误配置 - 路由not found未匹配：未发现错误
	app.OnErrorCode(iris.StatusNotFound, func(ctx iris.Context) {
		ctx.JSON(iris.Map{
			"status": iris.StatusNotFound,
			"msg":    "not found",
		})
	})

	// 500 为特定HTTP错误注册自定义处理程序方法
	// 当出现StatusInternalServerError内部错误返回500响应
	app.OnErrorCode(iris.StatusInternalServerError, func(ctx iris.Context) {
		// ctx.Values() 是一个很有用的东西，主要用来使 处理方法与中间件 通信 记住真的很重要
		// ctx.Values().GetString("error") 获取自定义错误提示信息
		errMessage := ctx.Values().GetString("error")
		if errMessage != "" {
			// ctx.Writef("Internal server error: %s", errMessage)
			ctx.JSON(iris.Map{
				"status": iris.StatusInternalServerError,
				"msg":    "interal error",
				"errmsg": errMessage,
			})
			return
		}
		ctx.JSON(iris.Map{
			"errmsg": iris.StatusInternalServerError,
			"msg":    "interal error",
			"data":   "(Unexpected) internal server error",
		})
	})
}

/**
 * MVC `路由配置`架构模式处理
 */
func mvcHandle(app *iris.Application) {

	//启用session
	// sessManager := sessions.New(sessions.Config{
	// 	Cookie:  "sessioncookie",
	// 	Expires: 24 * time.Hour,
	// })

	// engine := datasource.NewMysqlEngine()

	// //管理员模块功能
	// adminService := service.NewAdminService(engine)

	// admin := mvc.New(app.Party("/admin"))
	// admin.Register(
	// 	adminService,
	// 	sessManager.Start,
	// )
	// admin.Handle(new(controller.AdminController))

	// //用户功能模块
	// userService := service.NewUserService(engine)

	// user := mvc.New(app.Party("/v1/users"))
	// /user.Register(
	// 	userService,
	// 	sessManager.Start,
	// )
	// user.Handle(new(controller.UserController))

	// //统计功能模块
	// statisService := service.NewStatisService(engine)
	// statis := mvc.New(app.Party("/statis/{model}/{date}/"))
	// statis.Register(
	// 	statisService,
	// 	sessManager.Start,
	// )
	// statis.Handle(new(controller.StatisController))
}
